package com.hiultra.video.util;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hiultra.video.bean.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;

/**
 * 请求 wvp 服务器
 */
@Component
public class WVPNetUtil {

    public String USER_NAME = "admin";
    public String USER_PASSWORD = "21232f297a57a5a743894a0e4a801fc3";
    public String SERVER_URL = "http://127.0.0.1:8080";
    public String USER_LOGIN = "/api/user/login";
    public String DEVICE_LIST = "/api/device/query/devices";
    public String CHANNEL_LIST = "/api/device/query/devices/%s/channels";

    public String RECORD_QUERY ="/api/gb_record/query/%s/%s";
    public String RECORD_START ="/api/playback/start/%s/%s";
    public String RECORD_STOP ="/api/playback/stop/%s/%s/%s";
    public String PLAY = "/api/play/start/%s/%s";
    public String STOP = "/api/play/stop/%s/%s";

    private String accessToken;

    private RestTemplate restTemplate;

    public WVPNetUtil() {
        this.restTemplate = new RestTemplate();
    }

    JSONObject requestGet(String url) {
        return requestGet(url, new LinkedMultiValueMap<>());
    }

    public JSONObject requestGet(String url, MultiValueMap<String, String> queryParams) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Access-Token", accessToken);
        String responseString;
        JSONObject result;
        try {
            responseString = get(url, queryParams, headers);
            return new JSONObject(responseString);
        } catch (HttpClientErrorException.Unauthorized exception) {
            boolean isLogin = login();
            if (isLogin) {
                headers.get("Access-Token").clear();
                headers.add("Access-Token", accessToken);
                responseString = get(url, queryParams, headers);
                result = new JSONObject(responseString);
                return result;
            } else {
                return null;
            }
        } catch (HttpClientErrorException exception) {
            System.out.println(exception.getMessage());
            return null;
        }
    }

    String get(String url, MultiValueMap<String, String> queryParams) {
        return get(url, queryParams, new HttpHeaders());
    }

    String get(String url, MultiValueMap<String, String> queryParams, HttpHeaders headers) {
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(SERVER_URL + url).queryParams(queryParams);

        ResponseEntity<String> response = restTemplate.exchange(
                uriBuilder.toUriString(),
                HttpMethod.GET,
                new HttpEntity<>(null, headers),
                String.class
        );
        return response.getBody();
    }

    // 登录接口
    boolean login() {
        WVPNetUtil wvpNetUtil = new WVPNetUtil();
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("username", USER_NAME);
        params.add("password", USER_PASSWORD);
        String responseString = wvpNetUtil.get(USER_LOGIN, params, new HttpHeaders());
        JSONObject result = new JSONObject(responseString);
        if (result != null) {
            JSONObject data = result.getJSONObject("data");
            accessToken = data.getStr("accessToken");
            return true;
        }
        return false;
    }

    // 获取设备列表
    public List<Device> getDevices() throws JsonProcessingException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("page", "1");
        params.add("count", "100");

        JSONObject result = requestGet(DEVICE_LIST, params);
        JSONObject data = result.getJSONObject("data");
        JSONArray list = data.getJSONArray("list");
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(list.toString(), new TypeReference<List<Device>>() {
        });
    }

    // 获取设备通道列表
    public List<DeviceChannel> getChannels(String deviceId) throws JsonProcessingException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("page", "1");
        params.add("count", "100");
        JSONObject result = requestGet(String.format(CHANNEL_LIST, deviceId), params);
        JSONObject data = result.getJSONObject("data");
        JSONArray list = data.getJSONArray("list");
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(list.toString(), new TypeReference<List<DeviceChannel>>() {
        });
    }

    // 点播
    public StreamContent play(String deviceId, String channelId) throws Exception {
        JSONObject result = requestGet(String.format(PLAY, deviceId, channelId));
        if (result.getInt("code") == 0) {
            JSONObject data = result.getJSONObject("data");
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(data.toString(), new TypeReference<StreamContent>() {
            });
        } else {
            throw new Exception(result.getStr("msg"));
        }
    }
    // 停止
    public JSONObject stop(String deviceId, String channelId) throws Exception {
        JSONObject result = requestGet(String.format(STOP, deviceId, channelId));
        if (result.getInt("code") == 0) {
            JSONObject data = result.getJSONObject("data");
            return data;
        } else {
            throw new Exception(result.getStr("msg"));
        }
    }
    // 设备记录查询
    public DeviceRecord recordQuery(String deviceId,String channelId,String startTime,String endTime) throws JsonProcessingException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("startTime", startTime);
        params.add("endTime", endTime);
        JSONObject result = requestGet(String.format(RECORD_QUERY, deviceId,channelId), params);
        JSONObject data = result.getJSONObject("data");
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(data.toString(), new TypeReference<DeviceRecord>() {
        });
    }
    // 回放播放
    public VideoRecord recordStart(String deviceId,String channelId,String startTime,String endTime) throws JsonProcessingException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("startTime", startTime);
        params.add("endTime", endTime);
        JSONObject result = requestGet(String.format(RECORD_START, deviceId,channelId), params);
        JSONObject data = result.getJSONObject("data");
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(data.toString(), new TypeReference<VideoRecord>() {
        });
    }
    // 回放停止播放
    public JSONObject recordStop(String deviceId,String channelId,String stream) throws Exception {
        JSONObject result = requestGet(String.format(RECORD_STOP, deviceId, channelId,stream));
        if (result.getInt("code") == 0) {
            JSONObject data = result.getJSONObject("data");
            return data;
        } else {
            throw new Exception(result.getStr("msg"));
        }
    }

    public static void main(String[] args) {
        WVPNetUtil wvpNetUtil = new WVPNetUtil();
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("page", "1");
        params.add("count", "10");
        JSONObject jsonObject = wvpNetUtil.requestGet("/api/device/query/devices", params);
        System.out.println(jsonObject.toString());
    }

    void post() {

    }
}
